
// MFCD3D11TestDoc.cpp : implementation of the CMFCD3D11TestDoc class
//

#include "stdafx.h"
// SHARED_HANDLERS can be defined in an ATL project implementing preview, thumbnail
// and search filter handlers and allows sharing of document code with that project.
#ifndef SHARED_HANDLERS
#include "MFCD3D11Test.h"
#endif

#include "MFCD3D11TestDoc.h"
#include "DlgSetXYZParams.h"

#include <propkey.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// CMFCD3D11TestDoc

IMPLEMENT_DYNCREATE(CMFCD3D11TestDoc, CDocument)

BEGIN_MESSAGE_MAP(CMFCD3D11TestDoc, CDocument)
END_MESSAGE_MAP()


// CMFCD3D11TestDoc construction/destruction

CMFCD3D11TestDoc::CMFCD3D11TestDoc():m_iCurNormEstMethodMFiles(USEWEIGHTEDPCA_GAUSSIAN), m_iNFKernelSizeMFiles(3), m_fGaussSigmaMFiles(1.0f), m_fSampleWidthMFiles(70),
	m_fSampleHeightMfiles(55), m_fRTScaleRatio(0.9f), m_fRTThetaAng(0.0f), m_fRTPhiAng(0.0f)
{
	// TODO: add one-time construction code here

}

CMFCD3D11TestDoc::~CMFCD3D11TestDoc()
{
}

BOOL CMFCD3D11TestDoc::OnNewDocument()
{
	if (!CDocument::OnNewDocument())
		return FALSE;

	// TODO: add reinitialization code here
	// (SDI documents will reuse this document)

	return TRUE;
}




// CMFCD3D11TestDoc serialization

void CMFCD3D11TestDoc::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		// TODO: add storing code here
	}
	else
	{
		// TODO: add loading code here
	}
}

#ifdef SHARED_HANDLERS

// Support for thumbnails
void CMFCD3D11TestDoc::OnDrawThumbnail(CDC& dc, LPRECT lprcBounds)
{
	// Modify this code to draw the document's data
	dc.FillSolidRect(lprcBounds, RGB(255, 255, 255));

	CString strText = _T("TODO: implement thumbnail drawing here");
	LOGFONT lf;

	CFont* pDefaultGUIFont = CFont::FromHandle((HFONT) GetStockObject(DEFAULT_GUI_FONT));
	pDefaultGUIFont->GetLogFont(&lf);
	lf.lfHeight = 36;

	CFont fontDraw;
	fontDraw.CreateFontIndirect(&lf);

	CFont* pOldFont = dc.SelectObject(&fontDraw);
	dc.DrawText(strText, lprcBounds, DT_CENTER | DT_WORDBREAK);
	dc.SelectObject(pOldFont);
}

// Support for Search Handlers
void CMFCD3D11TestDoc::InitializeSearchContent()
{
	CString strSearchContent;
	// Set search contents from document's data. 
	// The content parts should be separated by ";"

	// For example:  strSearchContent = _T("point;rectangle;circle;ole object;");
	SetSearchContent(strSearchContent);
}

void CMFCD3D11TestDoc::SetSearchContent(const CString& value)
{
	if (value.IsEmpty())
	{
		RemoveChunk(PKEY_Search_Contents.fmtid, PKEY_Search_Contents.pid);
	}
	else
	{
		CMFCFilterChunkValueImpl *pChunk = NULL;
		ATLTRY(pChunk = new CMFCFilterChunkValueImpl);
		if (pChunk != NULL)
		{
			pChunk->SetTextValue(PKEY_Search_Contents, value, CHUNK_TEXT);
			SetChunkValue(pChunk);
		}
	}
}

#endif // SHARED_HANDLERS

// CMFCD3D11TestDoc diagnostics

#ifdef _DEBUG
void CMFCD3D11TestDoc::AssertValid() const
{
	CDocument::AssertValid();
}

void CMFCD3D11TestDoc::Dump(CDumpContext& dc) const
{
	CDocument::Dump(dc);
}
#endif //_DEBUG

BOOL CMFCD3D11TestDoc::GenerateHMFromAFM1DSlices(CXYZFileIO* pXYZFile)
{
	if(!pXYZFile)
		return FALSE;

	//Loop all the selected .xyz files!
	CString strSelectedFiles(m_strMAFMSliceFiles);
	strSelectedFiles.TrimLeft();
	strSelectedFiles.TrimRight();

	int iPos = strSelectedFiles.ReverseFind(_T('\\'));
	CString strFileNames = strSelectedFiles.Mid(iPos+1);
	CString strFileFolderPath = strSelectedFiles.TrimRight(strFileNames);
	strFileNames.TrimLeft();strFileNames.TrimRight();

	bool bFinished = false;
	//Get filtering method and sigma from GUI
	//
	CString strDebug("Generating XYZ File from Multiple AFM 1D Slices:");
	theApp.OutputString(strDebug);
	//clear array
	//array for saving the exitant energy
	std::vector<UtilityString> arrStrAFM1DSlicesFN;
	while (!bFinished)
	{
		CString strSingleFN;
		int iPos1 = strFileNames.Find(_T(' '));
		if(iPos1 >= 0)
			strSingleFN = strFileNames.Left(iPos1);
		else{
			strSingleFN = strFileNames;
			bFinished = true;
		}

		strFileNames.TrimLeft(strSingleFN);
		strFileNames.TrimLeft();
		CString strSingleFileFullPath = strFileFolderPath + strSingleFN;
		theApp.OutputString(strSingleFileFullPath);

		UtilityString ustrFN;
		ustrFN.SetWCharStr(strSingleFileFullPath.GetBuffer());
		arrStrAFM1DSlicesFN.push_back(ustrFN);		
	}
	CD3DUtilityFunction::fill2DHMWithAFM1DSlice(arrStrAFM1DSlicesFN,pXYZFile);
	strDebug.Format(_T("fSampleWidth=%f,fSampleHeight=%f\n"),pXYZFile->m_fSampleWidth, pXYZFile->m_fSampleHeight);
	theApp.OutputString(strDebug);

	//start the process
	//PostMessage(theMainWnd,WM_PROCESSXYZ_FINISHED,0,0);
	
	//save .xyz file
	UtilityString strAFMXYZ_FN(m_XYZFile.GetStrXYZFilePathName());
	strAFMXYZ_FN.Remove1LevelSubDirectory();
	strAFMXYZ_FN.ConcatenateStr("\\");

	UtilityString tmpFN;
	arrStrAFM1DSlicesFN[0].extracFNOnly(tmpFN);
	tmpFN.replaceExt("xyz");
	
	strAFMXYZ_FN.ConcatenateUtilityStr(tmpFN);

	//assign some parameters
	//start loading file
	/*line 1*/
	//string constant 
	NEW_CHAR_ARRAY(pXYZFile->m_strConstL1,MAX_PATH);
	strcpy(pXYZFile->m_strConstL1, m_XYZFile.m_strConstL1);
	/*line 2*/
	pXYZFile->m_iSoftwareType = m_XYZFile.m_iSoftwareType;
	pXYZFile->m_iMajorVers = m_XYZFile.m_iMajorVers;
	pXYZFile->m_iMinorVers = m_XYZFile.m_iMinorVers;
	pXYZFile->m_iBugVers = m_XYZFile.m_iBugVers;
	NEW_CHAR_ARRAY(pXYZFile->m_strSoftwareDate,MAX_PATH);
	strcpy(pXYZFile->m_strSoftwareDate, m_XYZFile.m_strSoftwareDate);
	/*line 3*/
	pXYZFile->m_iIntensOriginX = m_XYZFile.m_iIntensOriginX;
	pXYZFile->m_iIntensOriginY = m_XYZFile.m_iIntensOriginY;
	pXYZFile->m_iNBuckets = m_XYZFile.m_iNBuckets;
	pXYZFile->m_uiIntensRange = m_XYZFile.m_uiIntensRange;			
	/*line 4*/
	pXYZFile->m_iPhaseOriginX = m_XYZFile.m_iPhaseOriginX;
	pXYZFile->m_iPhaseOriginY = m_XYZFile.m_iPhaseOriginY;
	/*line 5*/
	NEW_CHAR_ARRAY(pXYZFile->m_strComment,MAX_PATH);
	strcpy(pXYZFile->m_strComment, m_XYZFile.m_strComment);			
	/*line 6*/
	NEW_CHAR_ARRAY(pXYZFile->m_strPartSerNum,MAX_PATH);
	strcpy(pXYZFile->m_strPartSerNum, m_XYZFile.m_strPartSerNum);						
	/*line 7*/
	NEW_CHAR_ARRAY(pXYZFile->m_strPartNum,MAX_PATH);
	strcpy(pXYZFile->m_strPartNum, m_XYZFile.m_strPartNum);									
	/*line 8*/
	pXYZFile->m_iSource = m_XYZFile.m_iSource;
	pXYZFile->m_fIntfScaleFactor = m_XYZFile.m_fIntfScaleFactor;
	pXYZFile->m_fWavelengthIn = m_XYZFile.m_fWavelengthIn;
	pXYZFile->m_fNumericAperture = m_XYZFile.m_fNumericAperture;
	pXYZFile->m_fObliquityFactor = m_XYZFile.m_fObliquityFactor;
	pXYZFile->m_fMagnification = m_XYZFile.m_fMagnification;
	pXYZFile->m_fCameraRes = m_XYZFile.m_fCameraRes;
	pXYZFile->m_iTimeStamp = m_XYZFile.m_iTimeStamp;			
	/*line 9*/
	pXYZFile->m_iSystemType = m_XYZFile.m_iSystemType;
	pXYZFile->m_iSystemBoard = m_XYZFile.m_iSystemBoard;
	pXYZFile->m_iSystemSerial = m_XYZFile.m_iSystemSerial;
	pXYZFile->m_iInstrumentId = m_XYZFile.m_iInstrumentId;
	NEW_CHAR_ARRAY(pXYZFile->m_strObjectiveName,MAX_PATH);
	strcpy(pXYZFile->m_strObjectiveName, m_XYZFile.m_strObjectiveName);				
	/*line 10*/
	pXYZFile->m_iAcquireMode = m_XYZFile.m_iAcquireMode;
	pXYZFile->m_iIntensAvgs = m_XYZFile.m_iIntensAvgs;
	pXYZFile->m_iPZTCal = m_XYZFile.m_iPZTCal;
	pXYZFile->m_iPZTGain = m_XYZFile.m_iPZTGain;
	pXYZFile->m_iPZTGainTolerance = m_XYZFile.m_iPZTGainTolerance;
	pXYZFile->m_iAGC = m_XYZFile.m_iAGC;
	pXYZFile->m_fTargetRange = m_XYZFile.m_fTargetRange;
	pXYZFile->m_fLightLevel = m_XYZFile.m_fLightLevel;
	pXYZFile->m_iMinMod = m_XYZFile.m_iMinMod;
	pXYZFile->m_iMinModPts = m_XYZFile.m_iMinModPts;
	/*line 11*/
	pXYZFile->m_iPhaseRes = m_XYZFile.m_iPhaseRes;
	pXYZFile->m_iPhaseAvgs = m_XYZFile.m_iPhaseAvgs;
	pXYZFile->m_iMinimumAreaSize = m_XYZFile.m_iMinimumAreaSize;
	pXYZFile->m_iDisconAction = m_XYZFile.m_iDisconAction;
	pXYZFile->m_fDisconFilter = m_XYZFile.m_fDisconFilter;
	pXYZFile->m_iConnectionOrder = m_XYZFile.m_iConnectionOrder;
	pXYZFile->m_iRemoveTiltBias = m_XYZFile.m_iRemoveTiltBias;
	pXYZFile->m_iDataSign = m_XYZFile.m_iDataSign;
	pXYZFile->m_iCodeVType = m_XYZFile.m_iCodeVType;
	/*line 12*/
	pXYZFile->m_iSubtractSysErr = m_XYZFile.m_iSubtractSysErr;
	NEW_CHAR_ARRAY(pXYZFile->m_strSysErrFile,MAX_PATH);
	strcpy(pXYZFile->m_strSysErrFile, m_XYZFile.m_strSysErrFile);		
	/*line 13*/
	pXYZFile->m_fRefractiveIndex = m_XYZFile.m_fRefractiveIndex;
	pXYZFile->m_fPartThickness = m_XYZFile.m_fPartThickness;
	/*line 14*/
	NEW_CHAR_ARRAY(pXYZFile->m_strZoomDesc,MAX_PATH);
	strcpy(pXYZFile->m_strZoomDesc, m_XYZFile.m_strZoomDesc);		

	//file name
	strcpy(pXYZFile->m_strXYZFileName, strAFMXYZ_FN.GetCharStr());
	bool bRt = pXYZFile->SaveXYZFile(pXYZFile->m_strXYZFileName, 0, pXYZFile->m_iHMDataHeight-1, 0, pXYZFile->m_iHMDataWidth-1);
	if(bRt){
		CString strDebug1;
		strDebug1.Format(L"%s is generated!", strAFMXYZ_FN.GetWCharStr());
		theApp.OutputString(strDebug1);
	}

	return TRUE;
}

DWORD _stdcall CMFCD3D11TestDoc::RaytracingVirtualGonioTestMFilesThread(void* pThis)
{
	CMFCD3D11TestDoc* pDoc = (CMFCD3D11TestDoc*)pThis;
	if (!pDoc)
		return 0;

	//start the process
	PostMessage(theMainWnd,WM_RAYTRACINGVGONIOMFILES_STARTED,0,0);

	//prepare the statistics file name
	UtilityString strRTStatFN(pDoc->m_XYZFile.m_strXYZFileName);
	strRTStatFN.Remove1LevelSubDirectory();
	strRTStatFN.ConcatenateStr("\\MultiXYZRTVGonio.txt");
	
	UtilityString strSumFN(pDoc->m_XYZFile.m_strXYZFileName);
	strSumFN.Remove1LevelSubDirectory();
	strSumFN.ConcatenateStr("\\MultiXYZRTVGonio_Sum.exr");
	
	UtilityString strFirstFN(pDoc->m_XYZFile.m_strXYZFileName);
	strFirstFN.Remove1LevelSubDirectory();
	strFirstFN.ConcatenateStr("\\MultiXYZRTVGonio_Single.exr");
	
	UtilityString strMultiFN(pDoc->m_XYZFile.m_strXYZFileName);
	strMultiFN.Remove1LevelSubDirectory();
	strMultiFN.ConcatenateStr("\\MultiXYZRTVGonio_Multiple.exr");
	

	//ray trace it!
	CRayTracingHM rtHM;
	D3DXVECTOR3 vRayDir;
	CD3DUtilityFunction::vecFromThetaPhi(vRayDir, pDoc->m_fRTThetaAng, pDoc->m_fRTPhiAng);
	vRayDir *= -1.0f;

	double iorIncidentReal = 1.0;
	double iorTransmittedReal = pDoc->GetXYZFile()->getFresnelIORReal();
	double iorTransmittedImg = pDoc->GetXYZFile()->getFresnelIORImg();
	//AL#4
	//double iorTransmittedReal = 0.963;
	//double iorTransmittedImg = 6.7;
	//Cu#4 --> use 680nm
	//double iorTransmittedReal = 0.2139;
	//double iorTransmittedImg = 3.9646;
	//Stainless
	//double iorTransmittedReal = 2.757;
	//double iorTransmittedImg = 3.792;

	//Loop all the selected .xyz files!
	CString strSelectedFiles(pDoc->m_strMXYZFiles);
	strSelectedFiles.TrimLeft();
	strSelectedFiles.TrimRight();

	int iPos = strSelectedFiles.ReverseFind(_T('\\'));
	CString strFileNames = strSelectedFiles.Mid(iPos+1);
	CString strFileFolderPath = strSelectedFiles.TrimRight(strFileNames);
	strFileNames.TrimLeft();strFileNames.TrimRight();

	bool bFinished = false;
	//Get filtering method and sigma from GUI
	//
	UtilityString strDebug("Start Ray Tracing Virtual Gonio From Multiple Files:");
	OutputDebugInfoThread(strDebug);
	//clear array
	//array for saving the exitant energy
	unsigned int iBufWidth = rtHM.getVGonioBufWidth();
	unsigned int iBufHeight = rtHM.getVGonioBufHeight();
	double* arrExitEnergy = new double[iBufWidth*iBufHeight];
	memset(arrExitEnergy,0,sizeof(double)*iBufWidth*iBufHeight);
	double* arrExitEnergy_Single = new double[iBufWidth*iBufHeight];
	memset(arrExitEnergy_Single,0,sizeof(double)*iBufWidth*iBufHeight);
	double* arrExitEnergy_Multiple = new double[iBufWidth*iBufHeight];
	memset(arrExitEnergy_Multiple,0,sizeof(double)*iBufWidth*iBufHeight);

	//record file
	FILE* fp = NULL;
	fopen_s(&fp,strRTStatFN.GetCharStr(),"w");

	while (!bFinished)
	{
		CString strSingleFN;
		int iPos1 = strFileNames.Find(_T(' '));
		if(iPos1 >= 0)
			strSingleFN = strFileNames.Left(iPos1);
		else
		{
			strSingleFN = strFileNames;
			bFinished = true;
		}
		strFileNames.TrimLeft(strSingleFN);
		strFileNames.TrimLeft();
		CString strSingleFileFullPath = strFileFolderPath + strSingleFN;
		UtilityString strSingleFN1(static_cast<wchar_t*>(strSingleFileFullPath.GetBuffer()));
		fprintf(fp,"%s\n",strSingleFN1.GetCharStr());

		//theApp.OutputString(strSingleFileFullPath);
		//process each file!
		CXYZFileIO* pSingleXYZFile = new CXYZFileIO();
		//load files
		if(pSingleXYZFile->LoadFromFile(CT2A(strSingleFileFullPath),pDoc->m_fSampleWidthMFiles,pDoc->m_fSampleHeightMfiles) < 0)
			return 0;
		//generate vertices
		bool bRt = pSingleXYZFile->GenerateVerticesPos(-0.5f,-0.5f);
		if (!bRt)
			return 0;
		//Vitrual gonio for current xyz file
		bRt = rtHM.Tracing2dHMDataVirutalGonio_OneOfMultiXYZFiles(*pSingleXYZFile, pDoc->m_fRTScaleRatio,vRayDir,arrExitEnergy, 
			arrExitEnergy_Single, arrExitEnergy_Multiple, iBufWidth, iBufHeight, iorIncidentReal, iorTransmittedReal, iorTransmittedImg);
		if(!bRt)
			return 0;
		
		//delete
		SAFE_DELETE(pSingleXYZFile);
		UtilityString strTmp(strSingleFileFullPath.GetBuffer());
		strDebug.GenerateFormatSmallString("%s processed!", strTmp.GetCharStr());
		OutputDebugInfoThread(strDebug);
	}
	//save the buffers out
	//save virtual gonio output results!
	double fMaxVal = -FLT_MAX;
	double fEnergySum = 0;
	double fEnergySingle = 0;
	double fEnergyMultiple = 0;
	for (unsigned int j = 0; j < iBufHeight; j++)
		for (unsigned int i = 0; i < iBufWidth; i++)
		{
			unsigned int iIdx = j*iBufWidth+i;
			double val = arrExitEnergy[iIdx];
			if(val > fMaxVal)
				fMaxVal = val;

			//accumulate energy
			fEnergySum += val;
			fEnergySingle += arrExitEnergy_Single[iIdx];
			fEnergyMultiple += arrExitEnergy_Multiple[iIdx];
		}
		fprintf(fp, "Ratio of Single Scattering:%f\n", (fEnergySingle)/fEnergySum);
		fprintf(fp, "Ratio of Multiple Scattering:%f\n", (fEnergyMultiple)/fEnergySum);
		//close record file!
		fclose(fp);
#if 0
	CRayTracingHM::Save2dGonioBufTo8BitImg(arrExitEnergy,iBufWidth,iBufHeight,strSumFN.GetCharStr(),0,fMaxVal,false);
	strDebug.GenerateFormatSmallString("%s saved!", strSumFN.GetCharStr());
	OutputDebugInfoThread(strDebug);
	CRayTracingHM::Save2dGonioBufTo8BitImg(arrExitEnergy_Single,iBufWidth,iBufHeight,strFirstFN.GetCharStr(),0,fMaxVal,false);
	strDebug.GenerateFormatSmallString("%s saved!", strFirstFN.GetCharStr());
	OutputDebugInfoThread(strDebug);
	CRayTracingHM::Save2dGonioBufTo8BitImg(arrExitEnergy_Multiple,iBufWidth,iBufHeight,strMultiFN.GetCharStr(),0,fMaxVal,false);
	strDebug.GenerateFormatSmallString("%s saved!", strMultiFN.GetCharStr());
	OutputDebugInfoThread(strDebug);
#else
	CRayTracingHM::Save2dGonioBufTo16BitImg(arrExitEnergy,iBufWidth,iBufHeight,strSumFN.GetCharStr(),0,fMaxVal,false);
	strDebug.GenerateFormatSmallString("%s saved!", strSumFN.GetCharStr());
	OutputDebugInfoThread(strDebug);
	CRayTracingHM::Save2dGonioBufTo16BitImg(arrExitEnergy_Single,iBufWidth,iBufHeight,strFirstFN.GetCharStr(),0,fMaxVal,false);
	strDebug.GenerateFormatSmallString("%s saved!", strFirstFN.GetCharStr());
	OutputDebugInfoThread(strDebug);
	CRayTracingHM::Save2dGonioBufTo16BitImg(arrExitEnergy_Multiple,iBufWidth,iBufHeight,strMultiFN.GetCharStr(),0,fMaxVal,false);
	strDebug.GenerateFormatSmallString("%s saved!", strMultiFN.GetCharStr());
	OutputDebugInfoThread(strDebug);
#endif
	strDebug.GenerateFormatSmallString("Finished Ray Tracing Virtual Gonio From Multiple Files!");
	OutputDebugInfoThread(strDebug);
	//release array memory
	SAFE_DELETE_ARRAY(arrExitEnergy);
	SAFE_DELETE_ARRAY(arrExitEnergy_Single);
	SAFE_DELETE_ARRAY(arrExitEnergy_Multiple);

	//start the process
	PostMessage(theMainWnd,WM_RAYTRACINGVGONIOMFILES_FINISHED,0,0);

	return 1;
}

DWORD _stdcall CMFCD3D11TestDoc::RaytracingVirtualGonioTestThread(void* pThis)
{
	CMFCD3D11TestDoc* pDoc = (CMFCD3D11TestDoc*)pThis;
	if (!pDoc)
		return 0;

	if(!pDoc->m_XYZFile.m_bDataReady)
		return 0;

	//start the process
	PostMessage(theMainWnd,WM_RAYTRACINGVGONIO_STARTED,0,0);

	//prepare the statistics file name
	UtilityString strRTStatFN(pDoc->m_XYZFile.m_strXYZFileName);
	UtilityString strFN;
	strRTStatFN.GetFileNameFromFullPath(strFN);
	strFN.replaceExt("stat");
	strRTStatFN.Remove1LevelSubDirectory();
	strRTStatFN.ConcatenateStr("\\");
	strRTStatFN.ConcatenateUtilityStr(strFN);


	UtilityString strSumFN(pDoc->m_XYZFile.m_strXYZFileName);
	UtilityString strTmpFN;
	strSumFN.GetFileNameFromFullPath(strTmpFN);
	UtilityString strSumFNOnly;
	strTmpFN.extractFNWithoutExt(strSumFNOnly);
	//strSumFNOnly.ConcatenateStr("_Sum.bmp");
	strSumFNOnly.ConcatenateStr("_Sum.exr");
	strSumFN.Remove1LevelSubDirectory();
	strSumFN.ConcatenateStr("\\");
	strSumFN.ConcatenateUtilityStr(strSumFNOnly);
	
	
	UtilityString strFirstFN(pDoc->m_XYZFile.m_strXYZFileName);
	UtilityString strFirstFNOnly;
	strTmpFN.extractFNWithoutExt(strFirstFNOnly);
	//strFirstFNOnly.ConcatenateStr("_Single.bmp");
	strFirstFNOnly.ConcatenateStr("_Single.exr");
	strFirstFN.Remove1LevelSubDirectory();
	strFirstFN.ConcatenateStr("\\");
	strFirstFN.ConcatenateUtilityStr(strFirstFNOnly);

	UtilityString strMultiFN(pDoc->m_XYZFile.m_strXYZFileName);
	UtilityString strMultiFNOnly;
	strTmpFN.extractFNWithoutExt(strMultiFNOnly);
	//strMultiFNOnly.ConcatenateStr("_Multiple.bmp");
	strMultiFNOnly.ConcatenateStr("_Multiple.exr");
	strMultiFN.Remove1LevelSubDirectory();
	strMultiFN.ConcatenateStr("\\");
	strMultiFN.ConcatenateUtilityStr(strMultiFNOnly);

	//ray trace it!
	CRayTracingHM rtHM;
	D3DXVECTOR3 vRayDir;
	CD3DUtilityFunction::vecFromThetaPhi(vRayDir, pDoc->m_fRTThetaAng, pDoc->m_fRTPhiAng);
	vRayDir *= -1.0f;
	//bool bRt = rtHM.Tracing2dHeightMapData(m_XYZFile,fScaleRatio,vRayDir,strRTStatFN.GetCharStr());
	double iorIncidentReal = 1.0;
	double iorTransmittedReal = 0.963;
	double iorTransmittedImg = 6.7;
	bool bRt = rtHM.Tracing2dHMDataVirutalGonio(pDoc->m_XYZFile,pDoc->m_fRTScaleRatio,vRayDir,strRTStatFN.GetCharStr(), strSumFN.GetCharStr(),
		strFirstFN.GetCharStr(),strMultiFN.GetCharStr(),iorIncidentReal, iorTransmittedReal, iorTransmittedImg);

	//start the process
	PostMessage(theMainWnd,WM_RAYTRACINGVGONIO_FINISHED,0,0);

	if(!bRt)
		return 0;

	return 1;
}

DWORD _stdcall CMFCD3D11TestDoc::RayTraceCurXYZFileStatisticsThread(void* pThis)
{
	CMFCD3D11TestDoc* pDoc = (CMFCD3D11TestDoc*)pThis;
	if (!pDoc)
		return 0;

	if(!pDoc->m_XYZFile.m_bDataReady)
		return 0;
	
	//start the process
	PostMessage(theMainWnd,WM_RAYTRACINGHMSTAT_STARTED,0,0);

	//prepare the statistics file name
	UtilityString strRTStatFN(pDoc->m_XYZFile.m_strXYZFileName);
	UtilityString strFN;
	strRTStatFN.GetFileNameFromFullPath(strFN);
	strFN.replaceExt("stat");
	strRTStatFN.Remove1LevelSubDirectory();
	strRTStatFN.ConcatenateStr("\\");
	strRTStatFN.ConcatenateUtilityStr(strFN);

	//ray trace it!
	CRayTracingHM rtHM;
	D3DXVECTOR3 vRayDir;
	CD3DUtilityFunction::vecFromThetaPhi(vRayDir, pDoc->m_fRTThetaAng, pDoc->m_fRTPhiAng);
	vRayDir *= -1.0f;
	//bool bRt = rtHM.Tracing2dHeightMapData(m_XYZFile,fScaleRatio,vRayDir,strRTStatFN.GetCharStr());
	bool bRt = rtHM.Tracing2dHeightMapData_RayOrder(pDoc->m_XYZFile,pDoc->m_fRTScaleRatio,vRayDir,strRTStatFN.GetCharStr());

	//start the process
	PostMessage(theMainWnd,WM_RAYTRACINGHMSTAT_FINISHED,0,0);

	if(!bRt)
		return 0;

	return 1;
}

DWORD _stdcall CMFCD3D11TestDoc::ComputeWaveOpticSingleFile(void* pThis)
{
	CMFCD3D11TestDoc* pDoc = (CMFCD3D11TestDoc*)pThis;
	if (!pDoc)
		return 0;

	PostMessage(theMainWnd, WM_COMPUTEWAVEOPTICBRDFSINGLEXYZ_STARTED, 0, 0);

	bool rt = pDoc->GetXYZFile()->computeWaveOpticBRDF();

	PostMessage(theMainWnd, WM_COMPUTEWAVEOPTICBRDFSINGLEXYZ_FINISHED, 0, 0);

	if(!rt)
		return 0;

	return 1;
}

DWORD _stdcall CMFCD3D11TestDoc::ComputeWaveOpticMultipleFiles(void* pThis)
{
	CMFCD3D11TestDoc* pDoc = (CMFCD3D11TestDoc*)pThis;
	if (!pDoc)
		return 0;

	PostMessage(theMainWnd, WM_COMPUTEWAVEOPTICBRDFMULTIPLEXYZ_STARTED, 0, 0);

	bool rt = pDoc->GetXYZFile()->computeWaveOpticBRDF_MultipleFiles(pDoc->m_strMXYZFiles,pDoc->m_fSampleWidthMFiles,pDoc->m_fSampleHeightMfiles);

	PostMessage(theMainWnd, WM_COMPUTEWAVEOPTICBRDFMULTIPLEXYZ_FINISHED, 0, 0);

	if(!rt)
		return 0;

	return 1;
}

DWORD _stdcall CMFCD3D11TestDoc::SetNormalWndSizeThread(void* pThis)
{
	CMFCD3D11TestDoc* pDoc = (CMFCD3D11TestDoc*)pThis;
	if (!pDoc)
		return 0;

	//start the process
	PostMessage(theMainWnd,WM_NORMALESTUPDATE_STARTED,0,0);

	bool rt = pDoc->GetXYZFile()->SetNewNormalWndSize(pDoc->m_iNormalWndSize);

	//start the process
	PostMessage(theMainWnd,WM_NORMALESTUPDATE_FINISHED,0,0);

	if(!rt)
		return 0;

	return 1;
}

DWORD _stdcall CMFCD3D11TestDoc::SetNFGaussianSigmaThread(void* pThis)
{
	CMFCD3D11TestDoc* pDoc = (CMFCD3D11TestDoc*)pThis;
	if (!pDoc)
		return 0;

	//start the process
	PostMessage(theMainWnd,WM_NORMALESTUPDATE_STARTED,0,0);

	bool rt = pDoc->GetXYZFile()->SetGaussianSigma(pDoc->m_fGaussSigma);
	
	//start the process
	PostMessage(theMainWnd,WM_NORMALESTUPDATE_FINISHED,0,0);
	
	if(!rt)
		return 0;
	return 1;
}



DWORD _stdcall CMFCD3D11TestDoc::EstimateNormXYZFile(void* pThis)
{
	CMFCD3D11TestDoc* pDoc = (CMFCD3D11TestDoc*)pThis;
	if (!pDoc)
		return 0;

	//start the process
	PostMessage(theMainWnd,WM_PROCESSXYZ_STARTED,0,0);

	bool rt = pDoc->GetXYZFile()->EstimateNormalForEachPoint();
	//bool rt = pDoc->GetXYZFile()->EstimateNormalForEachPoint_Eigen();

	if(!rt)
		return 0;

	//start the process
	PostMessage(theMainWnd,WM_PROCESSXYZ_FINISHED,0,0);

	return 1;
}

DWORD _stdcall CMFCD3D11TestDoc::EstimateNormMultiXYZFiles(void* pThis)
{
	CMFCD3D11TestDoc* pDoc = (CMFCD3D11TestDoc*)pThis;

	//start the process
	PostMessage(theMainWnd,WM_PROCESSMULTIXYZ_STARTED,0,0);
	if (!pDoc)
		return 0;

	bool rt = pDoc->GetXYZFile()->EstimateNormalForEachPoint_MultipleFiles(pDoc->m_strMXYZFiles,pDoc->m_iCurNormEstMethodMFiles, pDoc->m_iNFKernelSizeMFiles,
		pDoc->m_fGaussSigmaMFiles,pDoc->m_fSampleWidthMFiles,pDoc->m_fSampleHeightMfiles);

	if(!rt)
		return 0;
	
	//start the process
	PostMessage(theMainWnd,WM_PROCESSMULTIXYZ_FINISHED,0,0);

	return 1;
}

// CMFCD3D11TestDoc commands
DWORD _stdcall CMFCD3D11TestDoc::LoadXYZFileFromFile(void* pThis)
{
	CMFCD3D11TestDoc* pDoc = (CMFCD3D11TestDoc*)pThis;

	CDlgSetXYZParams dlg;
	if(IDOK != dlg.DoModal())
		return FALSE;

	float fWidth = dlg.m_fXYZWidth;
	float fHeight = dlg.m_fXYZHeight;
	//default values
	if(fWidth == 0) fWidth = 140;
	if(fHeight == 0) fHeight = 110;

	int iStitchID = dlg.m_iStitchTypeIdx;
	switch(iStitchID)
	{
	case 0:
		{
			fWidth = 70;
			fHeight = 55;
		}
		break;
	case 1:
		{
			fWidth = 120;
			fHeight = 90;
		}
		break;
	case 2:
		{
			fWidth = 230;
			fHeight = 170;
		}
		break;
	case 3:
		{
			fWidth = 440;
			fHeight = 330;
		}
		break;
	case 4:
		{
			fWidth = 810;
			fHeight = 55;
		}
		break;
	case 5:
		{
			fWidth = 70;
			fHeight = 610;
		}
		break;
	case 6:
		{
			fWidth = 70;
			fHeight = 110.5f;
		}
		break;
	case 7: 
		{
			fWidth = 70;
			fHeight = 57.5f;
		}
		break;
	case 8:
		{
			fWidth = 115.94f;
			fHeight = 55;
		}
		break;
	case 9:
		{
			fWidth = 113.96f;
			fHeight = 55;
		}
		break;
	case 10:
		{
			fWidth = 110;
			fHeight = 110;
		}
		break;
	case 11://paper test, 20xlens, 0.5x
		{
			fWidth = 710;
			fHeight = 530;
		}
		break;
	}

#if 0
	float fSigma =1.5f;
	float fPixelStep = 0.25f;
	std::vector<double> arrGaussVals;
	C3DUtilityFunction::Compute2DUniformGaussianKernel(fSigma,fPixelStep,arrGaussVals);
#endif

	//post finished message
	PostMessage(theMainWnd,WM_LOADXYZ_STARTED,0,0);
	
	if(pDoc->m_XYZFile.LoadFromFile(pDoc->m_strLoadXYZFN.GetCharStr(),fWidth,fHeight)<0)
		return FALSE;
	
	//post finished message
	PostMessage(theMainWnd,WM_LOADXYZ_FINISHED,0,0);
	
	return TRUE;
}

BOOL CMFCD3D11TestDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
	if(!lpszPathName)
		return FALSE;
	
	m_strLoadXYZFN.SetWCharStr((wchar_t*)(lpszPathName));

	//create thread
	HANDLE hth1 = ::CreateThread(NULL,0,LoadXYZFileFromFile,(LPVOID)this, 0, NULL);
	
	if(hth1)
	{
		CloseHandle(hth1);
		return TRUE;
	}
	else
		return FALSE;
}

BOOL CMFCD3D11TestDoc::ProcessXYZFile()
{
	//create thread
	HANDLE hth2 = ::CreateThread(NULL,0,EstimateNormXYZFile,(LPVOID)this, 0, NULL);

	if(hth2)
	{
		CloseHandle(hth2);
		return TRUE;
	}
	else
		return FALSE;
}

BOOL CMFCD3D11TestDoc::EstimateNormMFiles()
{
	//create thread
	HANDLE hth3 = ::CreateThread(NULL,0,EstimateNormMultiXYZFiles,(LPVOID)this, 0, NULL);

	if(hth3)
	{
		CloseHandle(hth3);
		return TRUE;
	}
	else
		return FALSE;
}

BOOL CMFCD3D11TestDoc::SetNormalWndSize(int iSize)
{
	m_iNormalWndSize = iSize;

	//create thread
	HANDLE hth4 = ::CreateThread(NULL,0,SetNormalWndSizeThread,(LPVOID)this, 0, NULL);

	if(hth4)
	{
		CloseHandle(hth4);
		return TRUE;
	}
	else
		return FALSE;
}

BOOL CMFCD3D11TestDoc::SetNFGaussianSigma(float fSigma)
{
	m_fGaussSigma = fSigma;

	//create thread
	HANDLE hth5 = ::CreateThread(NULL,0,SetNFGaussianSigmaThread,(LPVOID)this, 0, NULL);

	if(hth5)
	{
		CloseHandle(hth5);
		return TRUE;
	}
	else
		return FALSE;
}

BOOL CMFCD3D11TestDoc::RayTraceCurXYZFileStatistics()
{
	//create thread
	HANDLE hth5 = ::CreateThread(NULL,0,RayTraceCurXYZFileStatisticsThread,(LPVOID)this, 0, NULL);

	if(hth5)
	{
		CloseHandle(hth5);
		return TRUE;
	}
	else
		return FALSE;
}

BOOL CMFCD3D11TestDoc::RaytracingVirtualGonioTest()
{
	//create thread
	HANDLE hth6 = ::CreateThread(NULL,0,RaytracingVirtualGonioTestThread,(LPVOID)this, 0, NULL);

	if(hth6)
	{
		CloseHandle(hth6);
		return TRUE;
	}
	else
		return FALSE;
}

BOOL CMFCD3D11TestDoc::RaytracingVirtualGonioTest_MFiles()
{
	//create thread
	HANDLE hth7 = ::CreateThread(NULL,0,RaytracingVirtualGonioTestMFilesThread,(LPVOID)this, 0, NULL);

	if(hth7)
	{
		CloseHandle(hth7);
		return TRUE;
	}
	else
		return FALSE;
}

BOOL CMFCD3D11TestDoc::ComputeWaveOptic()
{
	HANDLE hth8 = ::CreateThread(NULL,0,ComputeWaveOpticSingleFile,(LPVOID)this, 0,NULL);
	if (hth8)
	{
		CloseHandle(hth8);
		return TRUE;
	} 
	else
		return FALSE;
}

BOOL CMFCD3D11TestDoc::ComputeWaveOpticMFiles()
{
	HANDLE hth9 = ::CreateThread(NULL,0,ComputeWaveOpticMultipleFiles,(LPVOID)this, 0,NULL);
	if(hth9)
	{
		CloseHandle(hth9);
		return TRUE;
	}
	else
		return FALSE;
}

//BOOL CMFCD3D11TestDoc::OnOpenDocument(LPCTSTR lpszPathName)
//{
//	// TODO:  Add your specialized creation code here
//	CDlgSetXYZParams dlg;
//	if(IDOK != dlg.DoModal())
//		return FALSE;
//
//	float fWidth = dlg.m_fXYZWidth;
//	float fHeight = dlg.m_fXYZHeight;
//	//default values
//	if(fWidth == 0) fWidth = 140;
//	if(fHeight == 0) fHeight = 110;
//
//	int iStitchID = dlg.m_iStitchTypeIdx;
//	switch(iStitchID)
//	{
//	case 0:
//		{
//			fWidth = 70;
//			fHeight = 55;
//		}
//		break;
//	case 1:
//		{
//			fWidth = 120;
//			fHeight = 90;
//		}
//		break;
//	case 2:
//		{
//			fWidth = 230;
//			fHeight = 170;
//		}
//		break;
//	case 3:
//		{
//			fWidth = 440;
//			fHeight = 330;
//		}
//		break;
//	case 4:
//		{
//			fWidth = 810;
//			fHeight = 55;
//		}
//		break;
//	case 5:
//		{
//			fWidth = 70;
//			fHeight = 610;
//		}
//		break;
//	case 6:
//		{
//			fWidth = 70;
//			fHeight = 110.5;
//		}
//		break;
//	case 7: 
//		{
//			fWidth = 70;
//			fHeight = 57.5;
//		}
//		break;
//	case 8:
//		{
//			fWidth = 115.94;
//			fHeight = 55;
//		}
//		break;
//	case 9:
//		{
//			fWidth = 113.96;
//			fHeight = 55;
//		}
//		break;
//	case 10:
//		{
//			fWidth = 110;
//			fHeight = 110;
//		}
//		break;
//	case 11://paper test, 20xlens, 0.5x
//		{
//			fWidth = 710;
//			fHeight = 530;
//		}
//		break;
//	}
//
//
//	if(m_XYZFile.LoadFromFile(CT2CA(lpszPathName),fWidth,fHeight)<0)
//		return FALSE;
//
//	return TRUE;
//}


//bool CMFCD3D11TestDoc::RayTraceCurXYZFileStatistics()
//{
//	if(!m_XYZFile.m_bDataReady)
//		return false;
//	//prepare the statistics file name
//	UtilityString strRTStatFN(m_XYZFile.m_strXYZFileName);
//	UtilityString strFN;
//	strRTStatFN.GetFileNameFromFullPath(strFN);
//	strFN.replaceExt("stat");
//	strRTStatFN.Remove1LevelSubDirectory();
//	strRTStatFN.ConcatenateStr("\\");
//	strRTStatFN.ConcatenateUtilityStr(strFN);
//
//	//ray trace it!
//	CRayTracingHM rtHM;
//	D3DXVECTOR3 vRayDir;
//	CD3DUtilityFunction::vecFromThetaPhi(vRayDir, m_fRTThetaAng, m_fRTPhiAng);
//	vRayDir *= -1.0f;
//	//bool bRt = rtHM.Tracing2dHeightMapData(m_XYZFile,fScaleRatio,vRayDir,strRTStatFN.GetCharStr());
//	bool bRt = rtHM.Tracing2dHeightMapData_RayOrder(m_XYZFile,m_fRTScaleRatio,vRayDir,strRTStatFN.GetCharStr());
//}